package com.fsoft.core.utils;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.X509TrustManager;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * Http上下文工具类
 * @package com.fsoft.core.utils
 * @author Fish
 * @email it.fish2010@foxmail.com
 * @create 2019-05-05
 * @copyright 2009-2019
 */
public class HttpContextUtils {

	public static HttpServletRequest getHttpServletRequest() {
		return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
	}

	public static String getCookieValue(String cookieName, HttpServletRequest request) {
		Cookie[] cookies = request.getCookies();
		if (cookies == null) {
			return null;
		}
		for (int i = 0; i < cookies.length; i++) {
			if (cookieName.equals(cookies[i].getName())) {
				return cookies[i].getValue();
			}
		}
		return null;
	}

	public static void setCookie(String cookieName, String cookieValue, HttpServletRequest request, HttpServletResponse response) {
		// String contextPath = request.getSession().getServletContext().getContextPath();
		// Cookie cookie = new Cookie(cookieName, cookieValue + "; HttpOnly");
		// cookie.setPath(contextPath);
		// cookie.setMaxAge(-1); // 关闭浏览器就失效。
		// response.addCookie(cookie);
		response.addHeader("Set-Cookie", cookieName + "=" + cookieValue);
	}

	public static void setCookie(String cookieName, String cookieValue, int expiry, HttpServletRequest request, HttpServletResponse response) {
		if (expiry < 0) {
			expiry = 0;
		}
		Cookie cookie = new Cookie(cookieName, cookieValue);
		cookie.setMaxAge(expiry);
		response.addCookie(cookie);
	}

	public static void removeCookie(String cookieName, HttpServletRequest request, HttpServletResponse response) {
		String contextPath = request.getSession().getServletContext().getContextPath();
		Cookie cookie = new Cookie(cookieName, null);
		cookie.setPath(contextPath);
		// 关闭浏览器就失效。
		cookie.setMaxAge(0);
		response.addCookie(cookie);
	}

	private static Log logger = LogFactory.getLog(HttpClientUtils.class);
	private static SSLConnectionSocketFactory sslsf = null;
	private static PoolingHttpClientConnectionManager cm = null;
	private static SSLContextBuilder builder = null;
	static {
		try {
			builder = new SSLContextBuilder();
			// 全部信任 不做身份鉴定
			builder.loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
					return true;
				}
			});
			sslsf = new SSLConnectionSocketFactory(builder.build(), new String[] { "SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2" }, null, NoopHostnameVerifier.INSTANCE);
			Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", new PlainConnectionSocketFactory()).register("https", sslsf).build();
			cm = new PoolingHttpClientConnectionManager(registry);
			cm.setMaxTotal(200);// max connection
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/***
	 * 无参数的get请求
	 * @author licheng
	 * @date 2021-03-03
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public static final JSONObject doGet(String url) throws Exception {
		return doGet(url, null);
	}

	/***
	 * 支持参数的GET请求
	 * @author licheng
	 * @date 2021-03-03
	 * @param url
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static final JSONObject doGet(String url, Map<String, String> params) throws Exception {
		JSONObject obj = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		try {
			client = getHttpClient();
			URIBuilder uri = new URIBuilder(url);
			List<NameValuePair> nvps = buildParams(params);
			if (OgnlUtils.isNotEmpty(nvps))
				uri.addParameters(nvps);
			HttpGet httpGet = new HttpGet(uri.build());
			httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=UTF-8"));
			httpGet.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"));
			response = client.execute(httpGet); // 请求服务
			obj = buildResponse(response);
		} catch (Exception e) {
			obj = null;
			logger.error("调用GET请求失败，请求地址：" + url + "，失败原因:" + e.getMessage(), e);
		} finally {
			close(response);
			close(client);
		}
		return obj;
	}

	/***
	 * 以post方式，发起HTTP请求
	 * @author licheng
	 * @date 2021-03-10
	 * @param url
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static final JSONObject doPost(String url, Map<String, String> params) throws Exception {
		JSONObject obj = null;
		CloseableHttpClient client = null;
		CloseableHttpResponse response = null;
		try {
			/* 创建一个httpclient对象 */
			client = getHttpClient();

			HttpPost httpPost = new HttpPost(url);
			// 设置post报文头
			httpPost.setHeader(new BasicHeader("Accept", "text/plain;charset=UTF-8"));
			httpPost.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"));
			// 设置请求参数
			StringEntity entity = new StringEntity(JSON.toJSONString(params), "UTF-8");
			httpPost.setEntity(entity);
			// 执行POST请求
			response = client.execute(httpPost);
			obj = buildResponse(response);
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("调用POST请求失败，请求地址：" + url + "，失败原因:" + e.getMessage(), e);
		} finally {
			close(response);
			close(client);
		}
		return obj;
	}

	/***
	 * 重组HTTP请求的参数
	 * @author licheng
	 * @date 2021-03-10
	 * @param params
	 * @return
	 */
	private static final List<NameValuePair> buildParams(Map<String, String> params) {
		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		if (OgnlUtils.isNotEmpty(params)) { // 请求参数不为空
			for (String key : params.keySet()) {
				if (OgnlUtils.isNotEmpty(params.get(key))) {
					try {
						NameValuePair nvp = new BasicNameValuePair(key, params.get(key));
						nvps.add(nvp);
					} catch (Exception e) {
						NameValuePair nvp = new BasicNameValuePair(key, "");
						nvps.add(nvp);
					}

				}
			}
		}
		return nvps;
	}

	/***
	 * 解析HTTP请求返回的结果
	 * @author licheng
	 * @date 2021-03-10
	 * @param response
	 * @return
	 */
	private static final JSONObject buildResponse(CloseableHttpResponse response) {
		if (response == null)
			return null;
		JSONObject json = null;
		// 请求响应码
		int statusCode = response.getStatusLine().getStatusCode();
		if (statusCode == 200) {
			try {
				/* 通过EntityUitls获取返回内容 */
				String result = EntityUtils.toString(response.getEntity(), "UTF-8");
				json = JSONObject.parseObject(result);
			} catch (Exception e) {
				json = null;
				logger.error("JSON转义请求结果异常:" + e.getMessage(), e);
			}
		}
		return json;
	}

	private static final void close(CloseableHttpClient client) {
		try {
			if (client != null)
				client.close();
		} catch (Exception e) {
			logger.error("关闭CloseableHttpClient异常：" + e.getMessage(), e);
		}
	}

	private static final void close(CloseableHttpResponse response) {
		try {
			if (response != null)
				response.close();
		} catch (Exception e) {
			logger.error("关闭CloseableHttpResponse异常：" + e.getMessage(), e);
		}
	}

	private static final CloseableHttpClient getHttpClient() {
		CloseableHttpClient httpClient = null;
		httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).setConnectionManager(cm).setConnectionManagerShared(true).build();
		return httpClient;
	}
}

/** 自定义的认证管理类 */
class PmsWechatTrustManager implements X509TrustManager {
	PmsWechatTrustManager() {
		// 这里可以进行证书的初始化操作
	}

	// 检查用户端的可信任状态
	public void checkClientTrusted(X509Certificate chain[], String authType) throws CertificateException {
	}

	// 检查服务器的可信任状态
	public void checkServerTrusted(X509Certificate chain[], String authType) throws CertificateException {
	}

	// 返回接受的发行商数组
	public X509Certificate[] getAcceptedIssuers() {
		return null;
	}
}
